#ifndef __POLL_SVR_H__
#define __POLL_SVR_H__

#include <iostream>
#include <string>
#include <vector>
#include <poll.h> // 包含poll相关的函数和数据结构定义
#include <sys/time.h> // 提供timeval等时间相关结构体
#include "Log.hpp" // 日志记录功能
#include "Sock.hpp" // 套接字操作封装

#define FD_NONE -1 // 定义一个表示未使用的文件描述符的标志

using namespace std;

// 使用poll实现的服务器类，相较于select，poll提供了更好的扩展性和灵活性
class PollServer
{
public:
    // 预设最大监控的文件描述符数量
    static const int nfds = 100;

    // 构造函数，初始化服务器，监听指定端口，默认为8080
    PollServer(const uint16_t &port = 8080) : _port(port), _nfds(nfds)
    {
        // 创建监听套接字
        _listensock = Sock::Socket();
        // 绑定端口
        Sock::Bind(_listensock, _port);
        // 开始监听
        Sock::Listen(_listensock);
        // 日志记录，表示基础套接字创建成功
        logMessage(DEBUG,"%s","create base socket success");

        // 分配pollfd数组，用于存储文件描述符及其事件
        _fds = new struct pollfd[_nfds];
        
        // 初始化pollfd数组，所有元素置为未使用状态
        for(int i = 0; i < _nfds; i++) {
            _fds[i].fd = FD_NONE;
            _fds[i].events = _fds[i].revents = 0;
        }
        
        // 设置监听套接字到pollfd数组的第一个元素，并关注其读事件
        _fds[0].fd = _listensock;
        _fds[0].events = POLLIN;

        // 设置超时时间，单位为毫秒
        _timeout = 1000;
    }

    // 启动服务器主循环，持续监听文件描述符事件并处理
    void Start()
    {
        while (true)
        {
            // 调用poll等待文件描述符事件
            int n = poll(_fds, _nfds, _timeout);
            // 根据poll返回值进行不同处理
            switch (n)
            {
            case 0: // 超时
                logMessage(DEBUG, "%s", "time out...");
                break;
            case -1: // 发生错误
                logMessage(WARNING, "poll error: %d : %s", errno, strerror(errno));
                break;
            default: // 成功，有事件发生
                // 处理就绪的文件描述符事件
                HandlerEvent();
                break;
            }
        }
    }

    // 析构函数，释放资源
    ~PollServer()
    {
        if (_listensock >= 0)
            close(_listensock); // 关闭监听套接字
        if (_fds) 
            delete [] _fds; // 释放pollfd数组内存
    }

private:
    // 事件处理函数，遍历pollfd数组，根据事件类型调用相应处理函数
    void HandlerEvent() 
    {
        for(int i = 0; i < _nfds; i++)
        {
            // 跳过无效的文件描述符
            if(_fds[i].fd == FD_NONE) continue;
            
            // 检查文件描述符是否有读事件就绪
            if(_fds[i].revents & POLLIN)
            {
                // 监听套接字有连接请求
                if(_fds[i].fd == _listensock) 
                    Accepter();
                // 其他套接字有数据可读
                else 
                    Recver(i);
            }
        }
    }

    // 处理新连接请求
    void Accepter()
    {
        string clientip;
        uint16_t clientport = 0;
        // 接受新连接
        int sock = Sock::Accept(_listensock, &clientip, &clientport);
        if(sock < 0)
        {
            logMessage(WARNING, "accept error");
            return;
        }
        // 记录新连接信息
        logMessage(DEBUG, "get a new line success : [%s:%d] : %d", clientip.c_str(), clientport, sock);
        
        // 将新连接的套接字加入监控
        int pos = 1;
        for(; pos < _nfds && _fds[pos].fd != FD_NONE; pos++);
        if(pos == _nfds)
        {
            // 数组已满，关闭新连接
            logMessage(WARNING, "poll server already full，close: %d", sock);
            close(sock);
        }
        else
        {
            _fds[pos].fd = sock;
            _fds[pos].events = POLLIN; // 关注读事件
        }
    }

    // 处理接收数据
    void Recver(int pos)
    {
        // 读事件就绪，处理数据
        logMessage(DEBUG, "message in, get IO event: %d", _fds[pos]);
        char buffer[1024];
        int n = recv(_fds[pos].fd, buffer, sizeof(buffer)-1, 0);
        if(n > 0)
        {
            buffer[n] = 0;
            logMessage(DEBUG, "client[%d]# %s", _fds[pos].fd, buffer);
        }
        else if(n == 0)
        {
            // 客户端断开连接
            logMessage(DEBUG, "client[%d] quit, me too...", _fds[pos].fd);
            // 关闭套接字并从监控列表移除
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
            _fds[pos].events = 0;
        }
        else
        {
            // 接收数据出错
            logMessage(WARNING, "%d sock recv error, %d : %s", _fds[pos].fd, errno, strerror(errno));
            // 关闭套接字并从监控列表移除
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
            _fds[pos].events = 0;
        }
    }

    // 打印当前监控的文件描述符信息，调试用途
    void DebugPrint()
    {
        cout << "_fds[]: ";
        for(int i = 0; i < _nfds; i++)
        {
            if(_fds[i].fd == FD_NONE) continue;
            cout << _fds[i].fd << " ";
        }
        cout << endl;
    }

private:
    uint16_t _port; // 监听端口号
    int _listensock; // 监听套接字
    struct pollfd *_fds; // pollfd数组，用于存储监控的文件描述符及其事件
    int _nfds; // pollfd数组的大小
    int _timeout; // poll超时时间，毫秒
};

#endif